/*
 * Copyright (c) zhg2yqq.com Corp.
 * All Rights Reserved.
 */
package com.zhg2yqq.wheels.mvc.base;

import java.io.Serializable;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.baomidou.mybatisplus.extension.kotlin.KtQueryChainWrapper;
import com.baomidou.mybatisplus.extension.kotlin.KtUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhg2yqq.wheels.common.exception.BusinessException;
import com.zhg2yqq.wheels.common.response.BaseResponseCode;
import com.zhg2yqq.wheels.mvc.MybatisEncryptProperties;
import com.zhg2yqq.wheels.mvc.wrapper.EncryptLambdaQueryChainWrapper;
import com.zhg2yqq.wheels.mvc.wrapper.EncryptLambdaQueryWrapper;
import com.zhg2yqq.wheels.mvc.wrapper.EncryptLambdaUpdateChainWrapper;
import com.zhg2yqq.wheels.mvc.wrapper.EncryptLambdaUpdateWrapper;
import com.zhg2yqq.wheels.mvc.wrapper.EncryptQueryChainWrapper;
import com.zhg2yqq.wheels.mvc.wrapper.EncryptQueryWrapper;
import com.zhg2yqq.wheels.mvc.wrapper.EncryptUpdateChainWrapper;
import com.zhg2yqq.wheels.mvc.wrapper.EncryptUpdateWrapper;

/**
 * @author zhg2yqq, 2022年12月3日
 * @version zhg2yqq v1.0
 */
public abstract class BaseService<M extends BaseMapper<T>, T> extends ServiceImpl<M, T>
        implements IBaseService<T> {
    @Autowired
    private MybatisEncryptProperties encryptProperties;

    public MybatisEncryptProperties getEncryptProperties() {
        return encryptProperties;
    }

    @Override
    public QueryChainWrapper<T> query() {
        return new EncryptQueryChainWrapper<>(encryptProperties.getPassword(), getEntityClass(),
                getBaseMapper());
    }

    @Override
    public QueryWrapper<T> queryWrapper() {
        return new EncryptQueryWrapper<>(encryptProperties.getPassword(), getEntityClass());
    }

    @Override
    public LambdaQueryChainWrapper<T> lambdaQuery() {
        return new EncryptLambdaQueryChainWrapper<>(encryptProperties.getPassword(),
                getEntityClass(), getBaseMapper());
    }

    @Override
    public LambdaQueryWrapper<T> lambdaQueryWrapper() {
        return new EncryptLambdaQueryWrapper<>(encryptProperties.getPassword(), getEntityClass());
    }

    @Override
    @Deprecated
    public KtQueryChainWrapper<T> ktQuery() {
        return super.ktQuery();
    }

    @Override
    @Deprecated
    public KtUpdateChainWrapper<T> ktUpdate() {
        return super.ktUpdate();
    }

    @Override
    public UpdateChainWrapper<T> update() {
        return new EncryptUpdateChainWrapper<>(encryptProperties.getPassword(), getEntityClass(),
                getBaseMapper());
    }

    @Override
    public UpdateWrapper<T> updateWrapper() {
        return new EncryptUpdateWrapper<>(encryptProperties.getPassword(), getEntityClass());
    }

    @Override
    public LambdaUpdateChainWrapper<T> lambdaUpdate() {
        return new EncryptLambdaUpdateChainWrapper<>(encryptProperties.getPassword(),
                getEntityClass(), getBaseMapper());
    }

    @Override
    public LambdaUpdateWrapper<T> lambdaUpdateWrapper() {
        return new EncryptLambdaUpdateWrapper<>(encryptProperties.getPassword(), getEntityClass());
    }

    @Override
    public boolean save(T entity) {
        this.saveCheck(entity);
        return super.save(entity);
    }

    @Override
    public boolean updateById(T entity) {
        this.updateCheck(entity);
        return super.updateById(entity);
    }

    @Override
    public boolean removeById(Serializable id) {
        T entity = this.getById(id);
        if (entity != null) {
            this.removeCheck(entity);
        }
        return super.removeById(id);
    }

    @Override
    public boolean removeById(Serializable id, boolean useFill) {
        T entity = this.getById(id);
        if (entity != null) {
            this.removeCheck(entity);
        }
        return super.removeById(id, useFill);
    }

    protected <U> U validEntityNotNull(U object) {
        return Optional.ofNullable(object)
                .orElseThrow(() -> BusinessException.of(BaseResponseCode.RESOURCE_NOT_EXISTS));
    }
}
